
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package model;

import exception.InvalidCommandException;
import exception.InvalidCommandReferenceException;
import java.lang.Thread.State;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author think
 */
public class CommandRunner {

    private static Queue<Executable> queuedCommands = new LinkedList<Executable>();
    private static List<Executable> runningCommands = new LinkedList<Executable>();
    private static CommandRunnnerThread runnerThread = new CommandRunnnerThread();
    private static boolean run;


    static {
        runnerThread.start();
    }

    public static void reset() {
        runningCommands.clear();
        queuedCommands.clear();
    }

    public static CommandRunnnerThread getRunnerThead() {
        return runnerThread;
    }

    public static void addCommand(Executable cmd) {
        queuedCommands.add(cmd);
    }

    public static Queue getQueuedCommands() {
        return queuedCommands;
    }

    public static List getRunningCommands() {
        return runningCommands;
    }

    public static void showRunningCommands() {
        Iterator it = runningCommands.iterator();
        System.out.println("running command:");
        while (it.hasNext()) {
            Executable cmd = (Executable) it.next();
            System.out.println(cmd.getCmd());
        }

    }

    public static void pause() {
        synchronized (runnerThread) {
            runnerThread.pause = true;
        }
    }

    public static void resume() {
        synchronized (runnerThread) {
            runnerThread.pause = false;
            runnerThread.notify();
        }
    }

    public static boolean isRunning() {
        State state = runnerThread.getState();
        if (state == State.WAITING) {
            return false;
        } else {
            return true;
        }
    }

    public static boolean isCommandRunning(String cmd){
        Iterator it = runningCommands.iterator();
        while(it.hasNext()){
            Command command = (Command)it.next();
            if(command.getCmd().equalsIgnoreCase(cmd))
                return true;
        }
        return false;
    }

    public static boolean isCommandQueued(String cmd) {
        Iterator it = queuedCommands.iterator();
        while(it.hasNext()){
            Command command = (Command)it.next();
            if(command.getCmd().equalsIgnoreCase(cmd))
                return true;
        }
        return false;
    }

    public static void main(String[] args) {
//        TSRunner.start();
        CommandRunner.resume();
        Command cmd1 = new Command("help");
        Command cmd2 = new Command("qma");
        Command cmd3 = new Command("qm win03uepinstall");
        CommandRunner.addCommand(cmd1);
        CommandRunner.addCommand(cmd2);
        CommandRunner.addCommand(cmd3);
        try {
            Thread.sleep(10000);
        } catch (InterruptedException ex) {
            Logger.getLogger(CommandRunner.class.getName()).log(Level.SEVERE, null, ex);
        }
        System.out.println(CommandRunner.getRunningCommands().size());
        System.out.println(CommandRunner.getQueuedCommands().size());
        System.out.println(cmd1.getOutput());
        System.out.println(cmd2.getOutput());
        System.out.println(cmd3.getOutput());
    }


    static public class CommandRunnnerThread extends Thread {

        boolean pause = false;
        private CommandRunner parent;

        public CommandRunnnerThread() {
            pause = false;
//            run();
        }

        @Override
        public void run() {
            while (true) {
                try {
                    synchronized (this) {
                        while (pause) {
                            this.wait();
                        }
                        if (getRunningCommands().size() > 0) {
                            Iterator it = getRunningCommands().iterator();
                            while (it.hasNext()) {
                                Executable cmd = (Executable) it.next();
                                if (cmd.finished()) {
                                    it.remove();
                                }
                            }
                        }
                        if (getQueuedCommands().size() > 0) {
                            Executable cmd = (Executable)getQueuedCommands().peek();
                            if (!isCommandRunningOnMachine(cmd.getMachine())) {
                                cmd = (Executable) getQueuedCommands().poll();
                                getRunningCommands().add(cmd);
                                try {
                                    cmd.run();
//                                    String result;
//                                    if(cmd.getResult()==0){
//                                        result = "s["+cmd.getCmd()+"]: "+cmd.getOutput();
//                                    }else{
//                                        result = "f["+cmd.getCmd()+"]: "+cmd.getOutput();
//                                    }
//                                    CmdResultManager.addResult(result);

//                                    CmdResultManager.addResult(cmd);
                                    CommandResultManager.addResult(cmd);
                                } catch (InvalidCommandReferenceException ex) {
                                    cmd.setResult(new CommandResult(1, ex.getMessage()));
                                    CommandResultManager.addResult(cmd);
                                } catch (InvalidCommandException ex) {
                                    cmd.setResult(new CommandResult(1,ex.getMessage()));
//                                    cmd.setResult(1);
//                                    cmd.setOutput(ex.getLocalizedMessage());
                                    
//                                    CmdResultManager.addResult(cmd);
                                    CommandResultManager.addResult(cmd);

//                                    CmdResultManager.addResult("f["+cmd.getCmd()+"]: "+ex.getMessage());
                                }
                            }
                        }

                    }
                    Thread.sleep(100);
                } catch (InterruptedException ex) {
                    Logger.getLogger(CommandRunner.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }

        boolean isCommandRunningOnMachine(VMMachine machine) {
            Iterator it = getRunningCommands().iterator();
            while (it.hasNext()) {
                Command cmd = (Command) it.next();
                if (cmd.getMachine()!=null && cmd.getMachine().equals(machine)) {
                    return true;
                }
            }
            return false;
        }
    }
}

